<?php

namespace app\common\service\shop\shopee;

use think\facade\Cache;

/**
 * shopee
 * @package app\common\service\shop\shopee
 * @Description shopee跨境平台接口服务
 * @author xuli
 * @date 2024-10-22 13:55
 */
class BaseApi
{
    public $partner_id = '';
    public $partner_key = '';
    //private $host = 'https://partner.shopeemobile.com'; // 生产环境
    private $host = 'https://partner.test-stable.shopeemobile.com'; // 测试环境
    public $access_token = '';
    protected $cache_token = 'shopee_token_';
    protected $cache_refresh_token = 'shopee_refresh_token_';
    protected $refresh_token = '';
    protected $shop_id = ''; // 系统店铺ID
    public $err_msg = '';

    // 授权信息--要存到表里，先写死
    public $auto_info = [
        'code' => '',
        'shop_id' => '',
        'main_account_id' => ''
    ];

    public function __construct()
    {
        $this->partner_id = '847892';
        $this->partner_key = '57615053704d6470644f554a78656d50484143644964436a5568777544524579';
    }

    /**
     * 生成店铺授权链接
     * @return string
     */
    public function autoShop()
    {
        $path = "/api/v2/shop/auth_partner";
        $redirectUrl = "https://www.baidu.com/"; // 回调地址

        $timest = time();
        $baseString = sprintf("%s%s%s", $this->partner_id, $path, $timest);
        $sign = hash_hmac('sha256', $baseString, $this->partner_key);
        $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s&redirect=%s", $this->host, $path, $this->partner_id, $timest, $sign, $redirectUrl);
        return $url;
    }

    public function getAccessToken()
    {
        $path = "/api/v2/auth/token/get";

        $timest = time();
        $body = array("code" => $this->auto_info['code'],  "shop_id" => $this->auto_info['shop_id'], "partner_id" => $this->partner_id);
        $baseString = sprintf("%s%s%s", $this->partner_id, $path, $timest);

        $sign = hash_hmac('sha256', $baseString, $this->partner_key);
        $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $this->host, $path, $this->partner_id, $timest, $sign);

        $result = $this->http_request('POST', $url, $body, ['Content-Type: application/json']);
        $result = json_decode($result, true);
        if($result) {
            if(!empty($result['access_token'])) {
                $this->access_token = $result['access_token'];
                // 缓存token
                Cache::set($this->cache_token . $this->auto_info['shop_id'], $this->access_token, 14400);
            }
            if(!empty($result['refresh_token'])) {
                $this->refresh_token = $result['refresh_token'];
                // 缓存刷新token
                Cache::set($this->cache_refresh_token . $this->auto_info['shop_id'], $this->refresh_token, 14400);
            }
            return true;
        } else {
            $this->err_msg = '获取token失败';
        }
        return false;
    }

    /**
     * 刷新token
     * @return bool
     */
    public function refreshAccessToken()
    {
        $path = "/api/v2/auth/access_token/get";

        $timest = time();
        $body = array("partner_id" => $this->partner_id, "shop_id" => $this->auto_info['shop_id'], "refresh_token" => $this->refresh_token);
        $baseString = sprintf("%s%s%s", $this->partner_id, $path, $timest);
        $sign = hash_hmac('sha256', $baseString, $this->partner_key);
        $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $this->host, $path, $this->partner_id, $timest, $sign);

        $result = $this->http_request('POST', $url, $body, ['Content-Type: application/json']);
        $result = json_decode($result, true);
        if($result) {
            if(!empty($result['access_token'])) {
                $this->access_token = $result['access_token'];
                // 缓存token
                Cache::set($this->cache_token . $this->auto_info['shop_id'], $this->access_token, 14400);
            }
            if(!empty($result['refresh_token'])) {
                $this->refresh_token = $result['refresh_token'];
                // 缓存刷新token
                Cache::set($this->cache_refresh_token . $this->auto_info['shop_id'], $this->refresh_token, 14400);
            }
            return true;
        } else {
            $this->err_msg = '刷新token失败';
        }
        return false;
    }

    public function shopApi($type, $shop_id, array $data = [])
    {
        // 通过shop_id 获取当前店铺token
        $this->shop_id = $shop_id;
        $this->getAllToken();

        $path = '';
        $time_st = time();
        $request_type = 'POST';
        $url = '';

        $baseString = sprintf("%s%s%s", $this->partner_id, $path, $time_st);
        $sign = hash_hmac('sha256', $baseString, $this->partner_key);

        switch ($type) {
            case 'get_category': // 获取分类列表
                $path = "/api/v2/product/get_category";
                $request_type = 'GET';
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                break;
            case 'get_attributes': // 获取属性
                $path = "/api/v2/product/get_attributes";
                $request_type = 'GET';
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                $this->splitStr($url, $data);
                break;
            case 'get_brand_list': // 获取品牌列表
                $path = "/api/v2/product/get_brand_list";
                $request_type = 'GET';
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                $this->splitStr($url, $data);
                break;
            case 'add_goods': // 添加商品
                $path = "/api/v2/product/add_item";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                break;
            case 'update_goods': // 编辑商品
                $path = "/api/v2/product/update_item";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                break;
            case 'upload_image': // 上传商品图片
                $path = "/api/v2/media_space/upload_image";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $sign);
                break;
            case 'search_goods': // 搜索商品
                $path = "/api/v2/product/search_item";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                $request_type = 'GET';
                $this->splitStr($url, $data);
                break;
            case 'goods_info': // 商品基础信息
                $path = "/api/v2/product/get_item_base_info";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                $request_type = 'GET';
                $this->splitStr($url, $data);
                break;
            case 'update_price': // 更新商品价格
                $path = "/api/v2/product/update_price";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                break;
            case 'update_stock': // 更新商品库存
                $path = "/api/v2/product/update_stock";
                $url = sprintf("%s%s?partner_id=%s&timestamp=%s&access_token=%s&shop_id=%s&sign=%s", $this->host, $path, $this->partner_id, $time_st, $this->access_token, $this->shop_id, $sign);
                break;
        }

        $result = $this->http_request($request_type, $url, $data, ['Content-Type: application/json']);
        return json_decode($result, true);
    }

    private function splitStr(&$url, $data)
    {
        $arr = [];
        foreach ($data as $k => $v) {
            $arr[] = $k . '=' . $v;
        }
        $url = $url . '&' . implode('&', $arr);
    }

    protected function getAllToken()
    {
        // 通过店铺ID获取到相关的appid配置或者
        $token = Cache::get($this->cache_token . $this->shop_id);
        if(!empty($token)) {
            $this->access_token = $token;
            return true;
        }
        // 当access_token不存在时重新请求token
        $this->refreshAccessToken();
    }

    private function http_request($type, $url, array $data, array $header)
    {
        $curl = curl_init();
        // curl参数配置-----------------------------------------
        $curl_params = [];
        //自定义header
        if(!empty($header)){
            $curl_params[CURLOPT_HTTPHEADER] = $header;
        }
        $curl_params[CURLOPT_URL] = $url; //请求url地址
        // $curl_params[CURLOPT_HEADER] = false; //是否返回响应头信息
        $curl_params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
        $curl_params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
        $curl_params[CURLOPT_MAXREDIRS] =  10; //指定最多的HTTP重定向的数量，这个选项是和CURLOPT_FOLLOWLOCATION一起使用的。
        $curl_params[CURLOPT_ENCODING] = ''; //支持的编码有"identity"，"deflate"和"gzip"。如果为空字符串""，请求头会发送所有支持的编码类型
        //$curl_params[CURLOPT_TIMEOUT] = 15; //设置cURL允许执行的最长秒数
        // $curl_params[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; //版本
        if(!empty($type)) {
            $curl_params[CURLOPT_CUSTOMREQUEST] = $type;
        }

        //如果有数据 则设置为post传输
        if (!empty($data)){
            $curl_params[CURLOPT_CUSTOMREQUEST] = 'POST';
            $curl_params[CURLOPT_POSTFIELDS] =  $data;
        }
        //下两行禁用证书
        $curl_params[CURLOPT_SSL_VERIFYPEER] = false;
        $curl_params[CURLOPT_SSL_VERIFYHOST] = false;
        // curl参数配置-----------------------------------------

        curl_setopt_array($curl, $curl_params);

        $response = curl_exec($curl);

        curl_close($curl);
        return $response;
    }


}
